package com.ruoyi.certificate.service.impl;

import com.ruoyi.certificate.domain.*;
import com.ruoyi.certificate.mapper.ZnlCertificateInfoEchartsMapper;
import com.ruoyi.certificate.service.IZnlCertificateInfoEchartsService;
import com.ruoyi.common.utils.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.ZoneId;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @author love ice
 * @create 2023-12-20 17:45
 */
@Service
public class ZnlCertificateInfoEchartsServiceImpl implements IZnlCertificateInfoEchartsService {
    @Autowired
    ZnlCertificateInfoEchartsMapper znlCertificateInfoEchartsMapper;

    @Override
    public GameTypeYearVo gameTypeYear() {
        GameTypeYearVo gameTypeYearVo = new GameTypeYearVo();
        List<List<String>> sourceList = new ArrayList<>();
        sourceList.add(Stream.of(
                "product", "国家级", "省部级", "地市级", "校级").collect(Collectors.toList()));
        List<GameTypeYearDo> gameTypeYearDos = znlCertificateInfoEchartsMapper.gameTypeYear();
        gameTypeYearDos.forEach(gameTypeYearDo -> {
            List<String> list = new ArrayList<>();
            list.add(gameTypeYearDo.getYear());
            list.add(gameTypeYearDo.getNationalCount());
            list.add(gameTypeYearDo.getProvinceCount());
            list.add(gameTypeYearDo.getCityCount());
            list.add(gameTypeYearDo.getSchoolCount());
            sourceList.add(list);
        });

        System.out.println(sourceList);
        gameTypeYearVo.setSource(sourceList);

        return gameTypeYearVo;
    }

    @Override
    public CertificateIncreaseVo certificateIncrease(CertificateIncreaseReq request) {
        if (Objects.isNull(request.getBeginTime()) || Objects.isNull(request.getEndTime())) {
            // 创建 Calendar 对象
            Calendar calendar = Calendar.getInstance();
            // 获取当前日期
            Date currentDate = new Date();
            System.out.println("当前日期: " + currentDate);
            // 将当前日期设置到 Calendar 对象中
            calendar.setTime(currentDate);
            // 从当前日期减去 30 天
            calendar.add(Calendar.DAY_OF_MONTH, -10);
            // 获取 10 天前的日期
            Date thirtyDaysAgo = calendar.getTime();
            request.setBeginTime(thirtyDaysAgo);
            request.setEndTime(currentDate);
        }
        CertificateIncreaseVo certificateIncreaseVo = new CertificateIncreaseVo();
        CertificateIncreaseVo.XAxis xAxis = certificateIncreaseVo.new XAxis();
        xAxis.setType("category");
        xAxis.setBoundaryGap(false);

        String beginTime = DateUtils.parseDateToStr("yyyy-MM-dd", request.getBeginTime());
        String endTime = DateUtils.parseDateToStr("yyyy-MM-dd", request.getEndTime());
        List<String> dataList = getDataList(beginTime, endTime);
        xAxis.setData(dataList);
        certificateIncreaseVo.setxAxis(xAxis);


        List<CertificateIncreaseDo> certificateInfoByDate = znlCertificateInfoEchartsMapper.getCertificateInfoByDate(
                request.getBeginTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDate(),
                request.getEndTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDate()
        );

        // 按照 certificateType 排序
        Map<String, List<CertificateIncreaseDo>> certificateIncreaseDoMap = certificateInfoByDate.stream().collect(Collectors.groupingBy(CertificateIncreaseDo::getCertificateType));

        // 时间、数组下标
        Map<String, Integer> dateIndexMap = dataList.stream().collect(Collectors.toMap(s -> s, dataList::indexOf));

        // 国家级
        List<String> nationalData = new ArrayList<>(Collections.nCopies(dataList.size(), "0"));
        // 省部级
        List<String> provinceData = new ArrayList<>(Collections.nCopies(dataList.size(), "0"));
        // 市级
        List<String> cityData = new ArrayList<>(Collections.nCopies(dataList.size(), "0"));
        // 校级
        List<String> schoolData = new ArrayList<>(Collections.nCopies(dataList.size(), "0"));

        certificateIncreaseDoMap.forEach((key, certificateIncreaseDoList) -> {
            if ("1".equals(key)) {
                // 国家级
                certificateIncreaseDoList.forEach(certificateIncreaseDo -> {
                    Integer indexOf = dateIndexMap.get(certificateIncreaseDo.getAcquisitionDate());
                    nationalData.set(indexOf, String.valueOf(certificateIncreaseDo.getCount()));
                });
            } else if ("2".equals(key)) {
                // 省部级
                certificateIncreaseDoList.forEach(certificateIncreaseDo -> {
                    Integer indexOf = dateIndexMap.get(certificateIncreaseDo.getAcquisitionDate());
                    provinceData.set(indexOf, String.valueOf(certificateIncreaseDo.getCount()));
                });
            } else if ("3".equals(key)) {
                // 市级
                certificateIncreaseDoList.forEach(certificateIncreaseDo -> {
                    Integer indexOf = dateIndexMap.get(certificateIncreaseDo.getAcquisitionDate());
                    cityData.set(indexOf, String.valueOf(certificateIncreaseDo.getCount()));
                });
            } else if ("4".equals(key)) {
                // 校级
                certificateIncreaseDoList.forEach(certificateIncreaseDo -> {
                    Integer indexOf = dateIndexMap.get(certificateIncreaseDo.getAcquisitionDate());
                    schoolData.set(indexOf, String.valueOf(certificateIncreaseDo.getCount()));
                });
            }
        });


        CertificateIncreaseVo.Series nationalSeries = structureSeries("国家级", "line", nationalData);
        CertificateIncreaseVo.Series provinceSeries = structureSeries("省部级", "line", provinceData);
        CertificateIncreaseVo.Series citySeries = structureSeries("地市级", "line", cityData);
        CertificateIncreaseVo.Series schoolSeries = structureSeries("校级", "line", schoolData);

        List<CertificateIncreaseVo.Series> seriesList = new ArrayList<>();
        seriesList.add(nationalSeries);
        seriesList.add(provinceSeries);
        seriesList.add(citySeries);
        seriesList.add(schoolSeries);
        certificateIncreaseVo.setSeries(seriesList);
        return certificateIncreaseVo;
    }

    /**
     * 根据 CertificateIncreaseReq 中的 certificateType 获取 CertificateRankTypeEnum 中对应的数据
     * CertificateRankTypeEnum 每个类型对应一个饼图数据
     *
     * @param request
     * @return
     */
    @Override
    public List<CertificateRankVo> certificateRank(CertificateIncreaseReq request) {

        // 如果前端没有传时间,默认获取当前时间
        Date year = Optional.ofNullable(request.getYear()).orElse(DateUtils.getNowDate());
        LocalDate localDate = year.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
        int yearInt = localDate.getYear();
        List<CertificateRankDo> certificateRankDoList;
        Map<Integer, Integer> map = new HashMap<>();
        CertificateRankTypeEnum certificateRankTypeEnum = CertificateRankTypeEnum.getByCode(String.valueOf(request.getCertificateType()));

        switch (certificateRankTypeEnum) {
            case CERTIFICATE_RANK:
                certificateRankDoList = znlCertificateInfoEchartsMapper.getCountByCertificateRank(yearInt);
                for (CertificateRankEnum myEnum : CertificateRankEnum.values()) {
                    map.put(myEnum.getCode(), 0);
                }
                certificateRankDoList.forEach(certificateRankDo -> map.put(Integer.valueOf(certificateRankDo.getDateKey()), certificateRankDo.getCount()));
                break;
            case CERTIFICATE_TYPE:
                certificateRankDoList = znlCertificateInfoEchartsMapper.getCountByCertificateType(yearInt);
                for (CertificateTyperEnum myEnum : CertificateTyperEnum.values()) {
                    map.put(myEnum.getCode(), 0);
                }
                certificateRankDoList.forEach(certificateRankDo -> map.put(Integer.valueOf(certificateRankDo.getDateKey()), certificateRankDo.getCount()));
                break;
            case GAME_TYPE:
                certificateRankDoList = znlCertificateInfoEchartsMapper.getGameType(yearInt);
                for (GameTyperEnum myEnum : GameTyperEnum.values()) {
                    map.put(myEnum.getCode(), 0);
                }
                certificateRankDoList.forEach(certificateRankDo -> map.put(Integer.valueOf(certificateRankDo.getDateKey()), certificateRankDo.getCount()));
                break;
            default:
                throw new IllegalArgumentException("Invalid certificate type");
        }

        return getCertificateRankVos(map,Integer.parseInt(certificateRankTypeEnum.getCode()));
    }

    /**
     * 遍历 map, 转化为 List<CertificateRankVo>
     *
     * @param map
     * @return
     */
    private static List<CertificateRankVo> getCertificateRankVos(Map<Integer, Integer> map, int type) {
        return map.entrySet().stream()
                .map(entry -> {
                    CertificateRankVo certificateRankVo = new CertificateRankVo();
                    certificateRankVo.setValue(entry.getValue());

                    switch (type) {
                        case 1:
                            certificateRankVo.setName(CertificateRankEnum.getDescriptionByCode(entry.getKey()));
                            break;
                        case 2:
                            certificateRankVo.setName(CertificateTyperEnum.getDescriptionByCode(entry.getKey()));
                            break;
                        case 3:
                            certificateRankVo.setName(GameTyperEnum.getDescriptionByCode(entry.getKey()));
                            break;
                        default:
                            certificateRankVo.setName("");
                            break;
                    }

                    return certificateRankVo;
                })
                .collect(Collectors.toList());
    }

    private CertificateIncreaseVo.Series structureSeries(String name, String type, List<String> data) {
        CertificateIncreaseVo certificateIncreaseVo = new CertificateIncreaseVo();
        CertificateIncreaseVo.Series series = certificateIncreaseVo.new Series();
        series.setName(name);
        series.setType(type);
        series.setData(data);
        return series;
    }


    private List<String> getDataList(String beginDateStr, String endDateStr) {

        LocalDate beginTime = LocalDate.parse(beginDateStr);
        LocalDate endTime = LocalDate.parse(endDateStr);

        List<String> dateList = new ArrayList<>();
        while (!beginTime.isAfter(endTime)) {
            dateList.add(beginTime.toString());
            beginTime = beginTime.plusDays(1);
        }

        System.out.println(dateList);
        return dateList;
    }

}
